﻿using System;
using System.Reflection;
using System.Reflection.Emit;

namespace OpenCompiler.CodeGen.Emit
{
	public class EmitManager
	{
		public static readonly EmitManager Instance = new EmitManager();

		private const string DynamicAssemblyName = "Dynamic Assembly";
		private const string DynamicModuleName = "Dynamic Module";


		private EmitManager()
		{
			this.Reset();
		}

		public AssemblyBuilder DynamicAssembly { get; private set; }

		public ModuleBuilder DynamicModule { get; private set; }

		public System.Reflection.Emit.TypeBuilder DefineType(string name, TypeAttributes attributes)
		{
			System.Reflection.Emit.TypeBuilder typeBuilder = this.DynamicModule.DefineType(name, attributes);
			return typeBuilder;
		}

		public void Reset()
		{
			this.DynamicAssembly = null;
			this.DynamicModule = null;

			string dynamicAssemblyName = DynamicAssemblyName + "_" + Guid.NewGuid().ToString();
			string dynamicModuleName = DynamicModuleName + "_" + Guid.NewGuid().ToString();
			
			this.DynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(dynamicAssemblyName),
																				 AssemblyBuilderAccess.RunAndSave);

			this.DynamicModule = this.DynamicAssembly.DefineDynamicModule(dynamicModuleName);
		}
	}
}
